package com.sites.cms.permission;

import java.util.Date;
import java.util.List;

import com.jfinal.core.Action;
import com.jfinal.core.JFinal;
import com.jfinal.kit.Ret;
import com.jfinal.kit.StrKit;
import com.jfinal.plugin.ehcache.CacheKit;
import com.sites.common.SiteInfo;
import com.sites.common.model.Permission;

/**
 * 权限处理服务层
 * 
 * @author zyg
 * 2020年1月29日 上午10:55:01
 */
public class PermissionService {

	private Permission dao = new Permission().dao();
	
	/**
	 * 从数据库获取所有权限
	 * @return
	 */
	public List<Permission> getAllPermission(){
		String sql = dao.getSql("permission.getAllPermission");
		return dao.find(sql, SiteInfo.siteId);
	}
	
	/**
	 * 获取所有启用状态的权限(用于角色权限分配)
	 * @return
	 */
	public List<Permission> getNormalPerms(){
		String sql = dao.getSql("permission.getNormalPerms");
		return dao.find(sql, SiteInfo.siteId);
	}
	
	/**
	 * 通过controller中的action同步所有的权限
	 * @return
	 */
	public Ret reloadPerm(){
		Ret ret = Ret.ok();
		
		int counter = 0;
		List<String> allActionKeys = JFinal.me().getAllActionKeys();
		for (String actionKey : allActionKeys) {
			// 只处理后台管理 action，其它跳过
			if (!actionKey.startsWith("/cms")) {
				continue ;
			}

			String[] urlPara = new String[1];
			Action action = JFinal.me().getAction(actionKey, urlPara);
			if (action == null) {
				continue ;
			}

			String controller = action.getControllerClass().getName();

			String sql = dao.getSql("permission.getByAction");
			Permission permission = dao.findFirst(sql, actionKey, controller, SiteInfo.siteId);

			//数据库中不存在的才保存到数据库
			if (permission == null) {
				permission = new Permission();
				permission.setActionKey(actionKey);
				permission.setController(controller);
				setRemarkValue(permission, action);
				permission.setSiteId(SiteInfo.siteId);
				permission.save();
				counter++;
			} else {
				// 如果 remark 字段是空值，才去尝试使用 @Remark 注解中的值
				if (StrKit.isBlank(permission.getRemark())) {
					setRemarkValue(permission, action);
					if (permission.update()) {
						counter++;
					}
				}
			}
		}

		if (counter == 0) {
			ret.set(SiteInfo.msgKey, "权限已经是最新状态，无需更新");
			ret.setOk();
		} else {
			ret.set(SiteInfo.msgKey, "权限更新成功，共更新权限数 : " + counter);
			CacheKit.removeAll(SiteInfo.permCacheName);//权限更新后清理所有权限缓存
		}
		
		return ret;
	}
	
	/**
	 * 根据action的remark注释更新数据库中的备注
	 * @param permission	数据库中的记录
	 * @param action		代码中的action
	 */
	private void setRemarkValue(Permission permission, Action action) {
		Remark remark = action.getMethod().getAnnotation(Remark.class);
		if (remark != null && StrKit.notBlank(remark.value())) {
			permission.setRemark(remark.value());
		}
	}
	
	/**
	 * 根据id获取权限记录
	 * @param id
	 * @return
	 */
	public Permission getById(int id){
		return dao.findById(id);
	}
	
	/**
	 * 更新数据库中的记录
	 * @param permission
	 * @return
	 */
	public Ret updatePerm(Permission permission){
		Ret ret = Ret.create();
		Permission temp = getById(permission.getId());
		temp.setRemark(permission.getRemark());
		temp.setStatus(permission.getStatus());
		boolean flag = temp.update();
		if(flag){
			ret.set(SiteInfo.msgKey, "更新成功");
			CacheKit.removeAll(SiteInfo.permCacheName);//权限更新后清理所有权限缓存
		} else {
			ret.set(SiteInfo.msgKey, "更新失败，请联系管理员！");
		}
		return ret;
	}
	
	/**
	 * 根据用户id获取用户拥有的权限(使用缓存)
	 * @param id	用户accountId
	 * @return
	 */
	public List<Permission> getAccountPerm(int id){
		String sql = dao.getSql("permission.getAccountPerm");
		//用户权限使用缓存，避免频繁查询数据库
		List<Permission> permList = dao.findByCache(SiteInfo.accPermCacheName, id, sql, id, SiteInfo.siteId);
		return permList;
	}
	
	/**
	 * 手动清理用户权限的缓存(主要用于用户分配新的权限时)
	 * @param accountId
	 */
	public void clearAccPermCache(int accountId){
		CacheKit.remove(SiteInfo.accPermCacheName, accountId);
	}
	
	/**
	 * 判断用户是否具有某个具体的操作权限(主要用于扩展指令ped)
	 * <br/>已删除的权限默认拥有
	 * @param actionKey		权限的actionKey
	 * @param accountId		用户id
	 * @return
	 */
	public boolean hasElementPerm(String actionKey, int accountId){
		//根据actionKey获取权限
		Permission permission = getByActionKey(actionKey, SiteInfo.siteId);
		if(permission == null){
			//当权限不存在时默认没有权限
			return false;
		}
		
		//判断权限状态
		String status = permission.getStatus();
		if(SiteInfo.statusDel.equals(status)){
			//当权限被删除时表示不需要限定，所有用户都有这个权限
			return true;
		}
		
		boolean flag = false;
		List<Permission> permList = getAccountPerm(accountId);
		for(int i=0,j=permList.size(); i<j; i++){
			if(actionKey.equals(permList.get(i).getActionKey())){
				flag = true;
				break;
			}
		}
		return flag;
	}
	
	/**
	 * 根据actionKey获取权限信息
	 * @param actionKey
	 * @return
	 */
	public Permission getByActionKey(String actionKey, int siteId){
		String sql = dao.getSql("permission.getByActionKey");
		Permission permission = dao.findFirstByCache(SiteInfo.permCacheName, actionKey, sql, actionKey, siteId);
		return permission;
	}
	
	/**
	 * 判断用户是有具有某几类操作权限(主要用于扩展指令pld)
	 * @param actionList	actionKey公共部分列表
	 * @param accountId		用户id
	 * @return
	 */
	public boolean hasListPerm(List<String> actionList, int accountId){
		boolean flag = false;
		List<Permission> permList = getAccountPerm(accountId);
		String actionKey,permActionKey;
		for(int i=0,j=actionList.size(); i<j; i++){
			actionKey = actionList.get(i);
			for(int m=0,n=permList.size(); m<n; m++){
				permActionKey = permList.get(m).getActionKey();
				if(permActionKey.indexOf(actionKey)>=0){
					flag = true;
					break;
				}
			}
			if(flag){
				break;
			}
		}
		return flag;
	}
	
	/**
	 * 删除权限信息
	 * @param id
	 * @return
	 */
	public Ret deletePerm(int id){
		Ret ret = Ret.create();
		Permission permission = dao.findById(id);
		permission.setStatus(SiteInfo.statusDel);
		permission.setUpdateTime(new Date());
		boolean flag = permission.update();
		if(flag){
			ret.setOk();
			ret.set(SiteInfo.msgKey, "删除成功");
			CacheKit.removeAll(SiteInfo.permCacheName);//权限更新后清理所有权限缓存
		} else {
			ret.setFail();
			ret.set(SiteInfo.msgKey, "删除失败，请联系管理员");
		}
		return ret;
	}
}
